#pragma once
#include <vector>
#include <string>

namespace _FOGGE_
{
	namespace _UTIL_
	{

		namespace _HELPER_
		{
		
			//----------------------------------------------------------------------------
			// @ Shuffle()
			// ---------------------------------------------------------------------------
			// Given a vector of data, perform the perfect shuffle algorithm, guaranteeing
			// that all elements in the vector end up in another position at the end
			//----------------------------------------------------------------------------
			template< class Type >
				void
				Shuffle( std::vector< Type >& dataSet )
			{
				unsigned index;

				if( dataSet.size() > 1 )
				{
					// Iterate through the dataSet, starting at the end, and swapping each
					// element for one at random beneath it. This is guaranteed to make each
					// element end up in another position at the end
					for( index = dataSet.size() - 1; index > 0; index-- )
					{
						Type swapValue;
						unsigned swapPoint;

						if( index > 1 )
						{
							swapPoint = ((unsigned) rand()) % (index - 1);
						}
						else
						{
							swapPoint = 0;
						}

						// Do the actual swap
						swapValue = dataSet[swapPoint];
						dataSet[swapPoint] = dataSet[index];
						dataSet[index] = swapValue;
					}
				}
			}	// End of Shuffle()		



			
			
			#define MAX_STRING_CONVERT_BUFFER_SIZE 100000
			extern char convertBuffer[MAX_STRING_CONVERT_BUFFER_SIZE];

			/**
			 Convert ansi code string to unicode string
			*/
			__forceinline void AnsiToUnicode(std::string& ansi, std::wstring &unicode)
			{
				int len = ::MultiByteToWideChar(CP_ACP, 0, ansi.c_str(), -1, NULL, 0);
				assert((len <MAX_STRING_CONVERT_BUFFER_SIZE)&&"(len >MAX_STRING_CONVERT_BUFFER_SIZE) _buffer overflow");
				wchar_t* pUnicode = reinterpret_cast<wchar_t* >(convertBuffer);
				::MultiByteToWideChar(CP_ACP, 0, ansi.c_str(), -1, pUnicode , len);
				unicode=pUnicode;
			}

			/**
			 Convert ansi code string to unicode string
			*/
			__forceinline  void AnsiToUnicode(char* pAnsi, std::wstring &unicode)
			{
				int len = ::MultiByteToWideChar(CP_ACP, 0, pAnsi, -1, NULL, 0);
				assert((len <MAX_STRING_CONVERT_BUFFER_SIZE)&&"(len >MAX_STRING_CONVERT_BUFFER_SIZE) _buffer overflow");
				wchar_t* pUnicode = reinterpret_cast<wchar_t* >(convertBuffer);
				::MultiByteToWideChar(CP_ACP, 0, pAnsi, -1, pUnicode , len);
				unicode=pUnicode;
			}

			 

			/**
			 Convert unicode string to unif8 code string
			*/
			__forceinline  void UnicodeToUtf8(std::wstring &unicode, std::string& utf8)
			{
				int len = ::WideCharToMultiByte(CP_UTF8, 0, unicode.c_str(), -1, NULL, 0, NULL, NULL);
				assert((len <MAX_STRING_CONVERT_BUFFER_SIZE)&&"(len >MAX_STRING_CONVERT_BUFFER_SIZE) _buffer overflow");
				char* pUtf8 = reinterpret_cast<char* >(convertBuffer);
				::WideCharToMultiByte(CP_UTF8, 0, unicode.c_str(), -1, pUtf8, len, NULL, NULL);
				utf8 = pUtf8;
			}

			 

			/**
			 Convert ansi code string to utf8 code string
			*/
			__forceinline  void AnsiToUtf8(std::string& ansi, std::string& utf8)
			{

				int len = ::MultiByteToWideChar(CP_ACP, 0, ansi.c_str(), -1, NULL, 0);
				wchar_t* pUnicode = reinterpret_cast<wchar_t* >(convertBuffer);
				::MultiByteToWideChar(CP_ACP, 0, ansi.c_str(), -1, pUnicode , len);

				char* pUtf8 = reinterpret_cast<char* >(pUnicode+ len +2);
				int len2 = ::WideCharToMultiByte(CP_UTF8, 0, pUnicode, -1, NULL, 0, NULL, NULL);

				assert((len +2+ len2<MAX_STRING_CONVERT_BUFFER_SIZE)&&"(len +2+ len2>MAX_STRING_CONVERT_BUFFER_SIZE) _buffer overflow");

				::WideCharToMultiByte(CP_UTF8, 0, pUnicode, -1, pUtf8, len2, NULL, NULL);
				utf8 = pUtf8;
			}
			/**
			 Convert ansi code string to utf8 code string
			*/
			__forceinline  void AnsiToUtf8(char* pAnsi, std::string& utf8)
			{

				int len = ::MultiByteToWideChar(CP_ACP, 0, pAnsi, -1, NULL, 0);
				wchar_t* pUnicode = reinterpret_cast<wchar_t* >(convertBuffer);
				::MultiByteToWideChar(CP_ACP, 0, pAnsi, -1, pUnicode , len);

				char* pUtf8 = reinterpret_cast<char* >(pUnicode+ len +2);
				int len2 = ::WideCharToMultiByte(CP_UTF8, 0, pUnicode, -1, NULL, 0, NULL, NULL);

				assert((len +2+ len2<MAX_STRING_CONVERT_BUFFER_SIZE)&&"(len +2+ len2>MAX_STRING_CONVERT_BUFFER_SIZE) _buffer overflow");

				::WideCharToMultiByte(CP_UTF8, 0, pUnicode, -1, pUtf8, len2, NULL, NULL);
				utf8 = pUtf8;
			}

			 

			/**
			 Convert utf8 code string to unicode string
			*/
			__forceinline  void Utf8ToUnicode(std::string& utf8, std::wstring &unicode)
			{   
				int len = ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0);
				assert((len <MAX_STRING_CONVERT_BUFFER_SIZE)&&"(len >MAX_STRING_CONVERT_BUFFER_SIZE) _buffer overflow");
				wchar_t* pUnicode = reinterpret_cast<wchar_t* >(convertBuffer);
				::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, pUnicode, len);
				unicode = pUnicode;
			}

			 

			/**
			 Convert unicode string to ansi code string
			*/
			__forceinline  void UnicodeToAnsi(std::wstring &unicode, std::string& ansi)
			{
				int len = ::WideCharToMultiByte(CP_ACP, 0, unicode.c_str(), -1, NULL, 0, NULL, NULL);
				assert((len <MAX_STRING_CONVERT_BUFFER_SIZE)&&"(len >MAX_STRING_CONVERT_BUFFER_SIZE) _buffer overflow");
				char* pAnsi = reinterpret_cast<char* >(convertBuffer);
				::WideCharToMultiByte(CP_ACP, 0, unicode.c_str(), -1, pAnsi, len, NULL, NULL);

				ansi = pAnsi;
			}

			 
			/**
			 Convert utf8 code string to ansi string
			*/
			__forceinline  void Utf8ToAnsi(std::string& utf8, std::string& ansi)
			{

				int len = ::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0);
				wchar_t* pUnicode = reinterpret_cast<wchar_t* >(convertBuffer);
				::MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, pUnicode, len);


				char* pAnsi = reinterpret_cast<char* >(pUnicode + len +2);
				
				int len2 = ::WideCharToMultiByte(CP_ACP, 0, pUnicode, -1, NULL, 0, NULL, NULL);


				assert((len +2+ len2<MAX_STRING_CONVERT_BUFFER_SIZE)&&"(len +2+ len2>MAX_STRING_CONVERT_BUFFER_SIZE) _buffer overflow");
				::WideCharToMultiByte(CP_ACP, 0, pUnicode, -1, pAnsi, len2, NULL, NULL);


				ansi = pAnsi; 

			}
		}
	}
}